#ifndef CBIGINT_H_
#define CBIGINT_H_

#include <ostream>
#include <sstream>
#include <string>
#include <math.h>
#include <cstdlib>
#include "../base/clinkedlist.h"

using namespace std;

#define chr(n) ((char)(n))
#define ord(c) ((int)(unsigned char)(c))

/**
 * CBigInt - class representing big integer numbers (represented by LLS)
 * @author Michal Rost
 * @date 12.02.2007
 */
class CBigInt : public CLinkedList<char> {
public:
  CBigInt();
  CBigInt(int num);
  CBigInt(long num);
  CBigInt(TItem<char>* h);
  CBigInt(const char str[]);
  CBigInt(string str);
  CBigInt(const CBigInt &num);
  CBigInt& operator = (const CBigInt &num);
  CBigInt& operator += (const CBigInt &num);
  CBigInt& operator -= (const CBigInt &num);
  CBigInt& operator *= (const CBigInt &num);
  CBigInt& operator /= (const CBigInt &num);
  CBigInt& operator ++ ();
  CBigInt& operator -- ();
  CBigInt operator ++ (int);
  CBigInt operator -- (int);
  CBigInt operator >> (const CBigInt &num) const;
  CBigInt operator << (const CBigInt &num) const;
  CBigInt operator + (const CBigInt &num) const;
  CBigInt operator - (const CBigInt &num) const;
  CBigInt operator * (const CBigInt &num) const;
  CBigInt operator / (const CBigInt &num) const;
  CBigInt operator % (const CBigInt &num) const;
  CBigInt operator - () const;
  bool operator == (const CBigInt &num) const;
  bool operator != (const CBigInt &num) const;
  bool operator >= (const CBigInt &num) const;
  bool operator <= (const CBigInt &num) const;
  bool operator < (const CBigInt &num) const;
  bool operator > (const CBigInt &num) const;
  bool operator ! () const;
  void negate();
  void setSign(int sign);
  CBigInt toNumberSystem(unsigned short nSystem);
  CBigInt getNumOfDigits();
  string toString() const;
  int getSign() const;
  long longValue() const;
  friend ostream& operator << (ostream &out, CBigInt &num) {
    return out << num.toString();
  }
  static string getClassName() {
    return "CBigInt";
  }
  static const int SIGN_NEGATIVE = 0;
  static const int SIGN_POSITIVE = 1;
private:
  int sign;
  CBigInt addAbs(TItem<char>* h1, TItem<char>* h2) const;
  CBigInt subAbs(TItem<char>* h1, TItem<char>* h2) const;
  CBigInt mulAbs(TItem<char>* h1, TItem<char>* h2) const;
  CBigInt divAbs(TItem<char>* h1, TItem<char>* h2, CBigInt &r) const;
  CBigInt divSAbs(TItem<char>* h1, TItem<char>* h2, CBigInt &r) const;
  int cmpAbs(TItem<char>* h1, TItem<char>* h2) const;
  void deleteRepeatingZeroes();
  void init(long num);
  void init(string str);
  void free();
  static const int ABS_LESSER = -1;
  static const int ABS_EQUAL = 0;
  static const int ABS_GREATER = 1;
};

#endif
